package concurrent.lock.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程之间的通信
 * <p>
 * 仿制SynchronousQueue
 *
 * @author LoneRanger
 */
public class ShareDataDemo {

	public static void main(String[] args) {

		ShareData shareData = new ShareData();

		// t1线程，生产
		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareData.increment();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t1").start();

		// t2线程，消费
		new Thread(() -> {
			for (int i = 0; i < 5; i++) {
				try {
					shareData.decrement();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}, "t2").start();
	}

}

class ShareData {

	private int num = 0;

	private Lock lock = new ReentrantLock();

	private Condition condition = lock.newCondition();

	public void increment() {
		//同步代码块
		lock.lock();
		try {
			//判断
			while (num != 0) {
				//等待不能生产
				System.out.println("incr -- await()");
				condition.await();
			}

			num++;

			System.out.println(Thread.currentThread().getName() + "num = " + num);

			//通知，唤醒
			condition.signalAll();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public void decrement() {
		//同步代码块
		lock.lock();
		try {
			while (num == 0) {
				System.out.println("decr -- await()");
				condition.await();
			}

			num--;

			System.out.println(Thread.currentThread().getName() + "num = " + num);

			//通知，唤醒
			condition.signalAll();


		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

}
